package org.aphelie.torg.ruler.internal.ui.editor.character;

import java.io.File;
import java.io.IOException;
import java.util.Locale;
import java.util.zip.ZipFile;

import org.aphelie.torg.ruler.core.character.CharacterRegistry;
import org.aphelie.torg.ruler.core.character.ICharacter;
import org.aphelie.torg.ruler.core.character.ICharacterBase;
import org.aphelie.torg.ruler.core.character.ICharacterModel;
import org.aphelie.torg.ruler.core.character.ICharacterModelBase;
import org.aphelie.torg.ruler.core.character.ICharacterObject;
import org.aphelie.torg.ruler.core.character.ISharedCharacterModel;
import org.aphelie.torg.ruler.internal.core.ICoreConstants;
import org.aphelie.torg.ruler.internal.core.character.WorkspaceCharacterModel;
import org.aphelie.torg.ruler.internal.core.character.WorkspaceCharacterModelBase;
import org.aphelie.torg.ruler.internal.core.project.TGRProject;
import org.aphelie.torg.ruler.internal.ui.ITGRUIConstants;
import org.aphelie.torg.ruler.internal.ui.TGRPlugin;
import org.aphelie.torg.ruler.internal.ui.editor.ISortableContentOutlinePage;
import org.aphelie.torg.ruler.internal.ui.editor.TGRLauncherFormEditor;
import org.aphelie.torg.ruler.internal.ui.editor.character.context.InputContext;
import org.aphelie.torg.ruler.internal.ui.editor.character.context.InputContextManager;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IShowEditorInput;
import org.eclipse.ui.IStorageEditorInput;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.ide.FileStoreEditorInput;
import org.eclipse.ui.part.FileEditorInput;

public class CharacterEditor extends TGRLauncherFormEditor implements IShowEditorInput {
	
	private static int BUILD_INDEX = 5;
	private static boolean SHOW_SOURCE;
	private boolean fEquinox = true;
	private boolean fShowExtensions = true;
	//TODO private IEclipsePreferences fPrefs;
	//TODO private PluginExportAction fExportAction;
	//TODO private ILauncherFormPageHelper fLauncherHelper;
	
	protected String getEditorID() {
		return ITGRUIConstants.CHARACTER_EDITOR_ID;
	}
	
	public static IEditorPart openPluginEditor(String id) {
		return openCharacterEditor(CharacterRegistry.findModel(id));
	}
/*
	public static IEditorPart openCharacterEditor(BundleDescription bd) {
		return openCharacterEditor(CharacterRegistry.findModel(bd));
	}
*/
	public static IEditorPart openCharacterEditor(ICharacterModelBase model) {
		if (model == null) {
			Display.getDefault().beep();
			return null;
		}
		return openCharacterEditor(model, false);
	}

	public static IEditorPart openCharacterEditor(ICharacterModelBase model, boolean source) {
		return open(model.getCharacterBase(), source);
	}

	public static IEditorPart open(Object object, boolean source) {
		SHOW_SOURCE = source;
		if (object instanceof ICharacterObject) {
			ISharedCharacterModel model = ((ICharacterObject) object).getModel();
			//if (model instanceof IBundleCharacterModelProvider)
				//model = ((IBundleCharacterModelProvider) model).getBundleCharacterModel();
			if (model instanceof ICharacterModelBase) {
				String filename = ((ICharacterModelBase) model).isFragmentModel() ? ICoreConstants.FRAGMENT_FILENAME_DESCRIPTOR : ICoreConstants.PLUGIN_FILENAME_DESCRIPTOR;
				//if (!(object instanceof ICharacterExtension) && !(object instanceof ICharacterExtensionPoint)) {
					String installLocation = model.getInstallLocation();
					if (installLocation == null)
						return null;
					File file = new File(installLocation);
					if (file.isFile()) {
						/*if (CoreUtility.jarContainsResource(file, ICoreConstants.BUNDLE_FILENAME_DESCRIPTOR, false)) {
							filename = ICoreConstants.BUNDLE_FILENAME_DESCRIPTOR;
						}*/
					} else if (new File(file, ICoreConstants.BUNDLE_FILENAME_DESCRIPTOR).exists()) {
						filename = ICoreConstants.BUNDLE_FILENAME_DESCRIPTOR;
					}
				//}
				IResource resource = model.getUnderlyingResource();
				if (resource == null)
					return openExternalCharacter(new File(model.getInstallLocation()), filename);
				return openWorkspaceCharacter(resource.getProject().getFile(filename));
			}
		}
		/*
		if (object instanceof BaseDescription) {
			//BundleDescription desc = ((BaseDescription) object).getSupplier();
			//String id = desc.getSymbolicName();
			//String version = desc.getVersion().toString();

			ModelEntry entry = CharacterRegistry.findEntry(id);
			ICharacterModelBase[] models = entry.getActiveModels();
			for (int i = 0; i < models.length; i++) {
				ICharacterModelBase model = models[i];
				//if (version.equals(model.getCharacterBase().getVersion()))
					//return open(model.getCharacterBase(), true);
			}
		}
		*/
		return null;
	}

	private static IEditorPart openWorkspaceCharacter(IFile pluginFile) {
		return openEditor(new FileEditorInput(pluginFile));
	}

	private static IEditorPart openExternalCharacter(File location, String filename) {
		IEditorInput input = null;
		if (location.isFile()) {
			try {
				ZipFile zipFile = new ZipFile(location);
				//if (zipFile.getEntry(filename) != null)
					//input = new JarEntryEditorInput(new JarEntryFile(zipFile, filename));
			} catch (IOException e) {
			}
		} else {
			File file = new File(location, filename);
			if (file.exists()) {
				IFileStore store;
				try {
					store = EFS.getStore(file.toURI());
					input = new FileStoreEditorInput(store);
				} catch (CoreException e) {
				}
			}
		}
		return openEditor(input);
	}

	public static IEditorPart openEditor(IEditorInput input) {
		if (input != null) {
			try {
				return TGRPlugin.getActivePage().openEditor(input, ITGRUIConstants.CHARACTER_EDITOR_ID);
			} catch (PartInitException e) {
				TGRPlugin.logException(e);
			}
		}
		return null;
	}

	
	protected void createResourceContexts(InputContextManager manager, IFileEditorInput input) {
		
		IFile characterFile = input.getFile();
		IFile modelFile = null;
		
		IContainer container = characterFile.getParent();
		String name = characterFile.getName().toLowerCase(Locale.ENGLISH);
		
		
		modelFile = createCharacterFile(container);
		
		/**
		try {
			modelFile.create(new InputStream() {
				
				@Override
				public int read() throws IOException {
					// TODO Auto-generated method stub
					return 0;
				}
			}, true, new NullProgressMonitor());
		} catch (CoreException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		final IEditorInput newInput;
		IFileStore modelFileStore;
		try {
			modelFileStore= EFS.getStore(((File) modelFile).toURI());
			newInput= new FileStoreEditorInput(modelFileStore);

			} catch (CoreException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		*/

		
		/*
		IFile file= getWorkspaceFile(modelFileStore);
		if (file != null)
			newInput= new FileEditorInput(file);
		else
		*/
			
		
		System.err.print("modelFile " + modelFile);
		
		
		
		FileEditorInput in = new FileEditorInput(characterFile);
		manager.putContext(in, new CharacterInputContext(this, in, true));
		manager.monitorFile(characterFile);
		
		
		//CDO
		System.out.println(manager.getAggregateModel().toString());
		ICharacterModel model = (ICharacterModel) manager.getAggregateModel();
		ICharacter character = model.getCharacter();
		
		/**
		IFile file = input.getFile();
		
		
		IFile manifestFile = null;
		IFile buildFile = null;
		IFile characterFile = null;
		boolean fragment = false;
		
		String name = file.getName().toLowerCase(Locale.ENGLISH);
		characterFile = createCharacterFile(container); //TODO CDO Forced
		if (name.equals(ICoreConstants.MANIFEST_FILENAME_LOWER_CASE)) {
			if (container instanceof IFolder)
				container = container.getParent();
			manifestFile = file;
			buildFile = container.getFile(ICoreConstants.BUILD_PROPERTIES_PATH);
			characterFile = createCharacterFile(container);
		} else if (true) {//TODO name.equals(ICoreConstants.PLUGIN_FILENAME_DESCRIPTOR) || name.equals(ICoreConstants.FRAGMENT_FILENAME_DESCRIPTOR)) {
			characterFile = file;
			fragment = name.equals(ICoreConstants.FRAGMENT_FILENAME_DESCRIPTOR);
			buildFile = container.getFile(ICoreConstants.BUILD_PROPERTIES_PATH);
			manifestFile = container.getFile(ICoreConstants.MANIFEST_PATH);
		}
		//TODO if (manifestFile.exists()) {
			//IEditorInput in = new FileEditorInput(manifestFile);
			//TODO Remove manager.putContext(in, new BundleInputContext(this, in, file == manifestFile));
		//}
		if (characterFile.exists()) {
			FileEditorInput in = new FileEditorInput(characterFile);
			manager.putContext(in, new CharacterInputContext(this, in, file == characterFile));
		}
		//if (buildFile.exists()) {
			//FileEditorInput in = new FileEditorInput(buildFile);
			//TODO Remove manager.putContext(in, new BuildInputContext(this, in, false));
		//}
		//manager.monitorFile(manifestFile);
		manager.monitorFile(characterFile);
		//manager.monitorFile(buildFile);
		 * 
		 */

		/** TODO
		fPrefs = new ProjectScope(container.getProject()).getNode(PDECore.PLUGIN_ID);
		if (fPrefs != null) {
			fShowExtensions = fPrefs.getBoolean(ICoreConstants.EXTENSIONS_PROPERTY, true);
			fEquinox = fPrefs.getBoolean(ICoreConstants.EQUINOX_PROPERTY, true);
		}
		*/
		
		
	}
	
	protected InputContextManager createInputContextManager() {
		CharacterInputContextManager contextManager = new CharacterInputContextManager(this);
		//TODO manager.setUndoManager(new PluginUndoManager(this));
		return (InputContextManager) contextManager;
	}
	
	public void monitoredFileAdded(IFile file) {
		if (fInputContextManager == null)
			return;
		String name = file.getName();
		/**
		if (name.equalsIgnoreCase(ICoreConstants.MANIFEST_FILENAME)) {
			if (!fInputContextManager.hasContext(BundleInputContext.CONTEXT_ID)) {
				IEditorInput in = new FileEditorInput(file);
				fInputContextManager.putContext(in, new BundleInputContext(this, in, false));
			}
		} else if (name.equalsIgnoreCase(ICoreConstants.PLUGIN_FILENAME_DESCRIPTOR)) {
			if (!fInputContextManager.hasContext(PluginInputContext.CONTEXT_ID)) {
				IEditorInput in = new FileEditorInput(file);
				fInputContextManager.putContext(in, new PluginInputContext(this, in, false, false));
			}
		} else if (name.equalsIgnoreCase(ICoreConstants.FRAGMENT_FILENAME_DESCRIPTOR)) {
			if (!fInputContextManager.hasContext(PluginInputContext.CONTEXT_ID)) {
				IEditorInput in = new FileEditorInput(file);
				fInputContextManager.putContext(in, new PluginInputContext(this, in, false, true));
			}
		} else if (name.equalsIgnoreCase(ICoreConstants.BUILD_FILENAME_DESCRIPTOR)) {
			if (!fInputContextManager.hasContext(BuildInputContext.CONTEXT_ID)) {
				IEditorInput in = new FileEditorInput(file);
				fInputContextManager.putContext(in, new BuildInputContext(this, in, false));
			}
		}*/
	}

	public void ensurePluginContextPresence() {
		if (fInputContextManager.hasContext(CharacterInputContext.CONTEXT_ID))
			return;
		IProject project = fInputContextManager.getCommonProject();
		WorkspaceCharacterModelBase model = null;
		IFile file = null;
		//TODO if (fInputContextManager.getAggregateModel() instanceof IFragmentModel) {
		//	file = TGRProject.getFragmentXml(project);
		//	//model = new WorkspaceFragmentModel(file, false);
		//} else {
			file = TGRProject.getCharacterXml(project);
			model = new WorkspaceCharacterModel(file, false);
		//}

		ICharacterBase pluginBase = model.getCharacterBase(true);
		/** TODO
		try {
			pluginBase.setSchemaVersion(TargetPlatformHelper.getSchemaVersion());
		} catch (CoreException e) {
		}
		*/
		model.save();
		IEditorInput in = new FileEditorInput(file);
		fInputContextManager.putContext(in, new CharacterInputContext(this, in, false));

		// TODO updateBuildProperties(file.getName());
	}

	/** TODO
	private void updateBuildProperties(String filename) {
		try {
			InputContext context = fInputContextManager.findContext(BuildInputContext.CONTEXT_ID);
			if (context != null) {
				IBuildModel buildModel = (IBuildModel) context.getModel();
				IBuild build = buildModel.getBuild();
				IBuildEntry entry = build.getEntry("bin.includes"); //$NON-NLS-1$
				if (entry == null) {
					entry = buildModel.getFactory().createEntry("bin.includes"); //$NON-NLS-1$
					build.add(entry);
				}
				if (!entry.contains(filename))
					entry.addToken(filename);
			}
		} catch (CoreException e) {
		}
	}
*/

	public boolean monitoredFileRemoved(IFile file) {
		//TODO may need to check with the user if there
		//are unsaved changes in the model for the
		//file that just got removed under us.
		return true;
	}

	public void editorContextAdded(InputContext context) {
		addSourcePage(context.getId());
		//TODO try {
			//if (context.getId().equals(BuildInputContext.CONTEXT_ID))
				//addPage(BUILD_INDEX, new BuildPage(this));
			//else {
				updateFirstThreePages();
		//	}
		//} catch (PartInitException e) {
		//	TGRPlugin.logException(e);
		//}
	}

	public void contextRemoved(InputContext context) {
		close(true);
	}

	private void updateFirstThreePages() {
		try {
			int index = getActivePage();
			removePage(0);
			removePage(0);
			removePage(0);
			//TODO addPage(0, new RuntimePage(this));
			//TODO addPage(0, new DependenciesPage(this));
			addPage(0, new OverviewPage(this));
			setActivePage(index);
		} catch (PartInitException e) {
			TGRPlugin.logException(e);
		}
	}
	
	protected void createSystemFileContexts(InputContextManager manager, FileStoreEditorInput input) {
		File file = new File(input.getURI());
		File manifestFile = null;
		File buildFile = null;
		File characterFile = null;
		String name = file.getName().toLowerCase(Locale.ENGLISH);
		//if (name.equals(ICoreConstants.MANIFEST_FILENAME_LOWER_CASE)) {
			//manifestFile = createCharacterFile(dir);
			//manifestFile.createNewFile();
			File dir = file.getParentFile().getParentFile();
			buildFile = new File(dir, ICoreConstants.BUILD_FILENAME_DESCRIPTOR);
			characterFile = createCharacterFile(dir);
			manifestFile = createCharacterFile(dir);
			try {
			manifestFile.createNewFile();
			} catch (IOException e) {
				TGRPlugin.logException(e);
			}
			
		/*} else if (name.equals(ICoreConstants.BUILD_FILENAME_DESCRIPTOR)) {
			buildFile = file;
			File dir = file.getParentFile();
			characterFile = createCharacterFile(dir);
			manifestFile = new File(dir, ICoreConstants.BUNDLE_FILENAME_DESCRIPTOR);
		} else if (name.equals(ICoreConstants.PLUGIN_FILENAME_DESCRIPTOR) || name.equals(ICoreConstants.FRAGMENT_FILENAME_DESCRIPTOR)) {
			characterFile = file;
			File dir = file.getParentFile();
			buildFile = new File(dir, ICoreConstants.BUILD_FILENAME_DESCRIPTOR);
			manifestFile = new File(dir, ICoreConstants.BUNDLE_FILENAME_DESCRIPTOR);
		}*/
		try {
			if (manifestFile.exists()) {
				IFileStore store = EFS.getStore(manifestFile.toURI());
				IEditorInput in = new FileStoreEditorInput(store);
				//TODOmanager.putContext(in, new BundleInputContext(this, in, file == manifestFile));
			}
			if (characterFile.exists()) {
				IFileStore store = EFS.getStore(characterFile.toURI());
				IEditorInput in = new FileStoreEditorInput(store);
				manager.putContext(in, new CharacterInputContext(this, in, file == characterFile));
			}
			if (buildFile.exists()) {
				IFileStore store = EFS.getStore(buildFile.toURI());
				IEditorInput in = new FileStoreEditorInput(store);
				//manager.putContext(in, new BuildInputContext(this, in, file == buildFile));
			}
		} catch (CoreException e) {
			TGRPlugin.logException(e);
		}
	}
	
	private File createCharacterFile(File dir) {
		File pluginFile = new File(dir, ICoreConstants.PLUGIN_FILENAME_DESCRIPTOR);
		if (!pluginFile.exists())
			pluginFile = new File(dir, ICoreConstants.FRAGMENT_FILENAME_DESCRIPTOR);
		return pluginFile;
	}
		
	private IFile createCharacterFile(IContainer container) {
		IFile characterFile = container.getFile(ICoreConstants.PLUGIN_PATH);
		if (!characterFile.exists())
			characterFile = container.getFile(ICoreConstants.FRAGMENT_PATH);
		return characterFile;
	}
	
	protected void createStorageContexts(InputContextManager manager, IStorageEditorInput input) {
		/** TODO if (input instanceof JarEntryEditorInput) {
			createJarEntryContexts(manager, (JarEntryEditorInput) input);
			return;
		}
*/
		String name = input.getName().toLowerCase(Locale.ENGLISH);
		//if (name.startsWith(ICoreConstants.MANIFEST_FILENAME_LOWER_CASE)) {
			//manager.putContext(input, new BundleInputContext(this, input, true));
		//} else if (name.startsWith(ICoreConstants.BUILD_FILENAME_DESCRIPTOR)) {
			//manager.putContext(input, new BuildInputContext(this, input, true));
		//} else if (name.startsWith(ICoreConstants.PLUGIN_FILENAME_DESCRIPTOR)) {
			manager.putContext(input, new CharacterInputContext(this, input, true));
		//} else if (name.startsWith(ICoreConstants.FRAGMENT_FILENAME_DESCRIPTOR)) {
			//manager.putContext(input, new CharacterInputContext(this, input, true));
		//}
	}	
	
	

	
	protected void addEditorPages() {
		try {
			addPage(new OverviewPage(this));
			//addPage(new DependenciesPage(this));
			//addPage(new RuntimePage(this));
			
			//addPage(new DraftSourcePage(this));
			/**
			if (showExtensionTabs()) {
				addExtensionTabs();
			}
			if (fInputContextManager.hasContext(BuildInputContext.CONTEXT_ID))
				addPage(new BuildPage(this));
				*/
		} catch (PartInitException e) {
			TGRPlugin.logException(e);
		}

		//TODOaddSourcePage(BundleInputContext.CONTEXT_ID);
		addSourcePage(CharacterInputContext.CONTEXT_ID);
		
		
		
		//TODOaddSourcePage(BuildInputContext.CONTEXT_ID);
	}
	
	protected ISortableContentOutlinePage createContentOutline() {
		return null;//TODO new ManifestOutlinePage(this);
	}
	
	
	
	
	
	
	
	
	
	
	
	
	
	

	protected InputContext getInputContext(Object object) {
		InputContext context = null;
		if (object instanceof IFile) {
			String name = ((IFile) object).getName();
			if (name.equals(ICoreConstants.PLUGIN_FILENAME_DESCRIPTOR) || name.equals(ICoreConstants.FRAGMENT_FILENAME_DESCRIPTOR))
				context = fInputContextManager.findContext(CharacterInputContext.CONTEXT_ID);
			//else if (name.equals(ICoreConstants.MANIFEST_FILENAME))
				//context = fInputContextManager.findContext(BundleInputContext.CONTEXT_ID);
			//else if (name.equals(ICoreConstants.BUILD_FILENAME_DESCRIPTOR))
				//context = fInputContextManager.findContext(BuildInputContext.CONTEXT_ID);
		//} else if (object instanceof IBuildObject) {
		//	context = fInputContextManager.findContext(BuildInputContext.CONTEXT_ID);
		//} else if (object instanceof IPluginExtensionPoint || object instanceof IPluginExtension) {
		//	context = fInputContextManager.findContext(PluginInputContext.CONTEXT_ID);
		} else {
			//context = fInputContextManager.findContext(BundleInputContext.CONTEXT_ID);
			if (context == null)
				context = fInputContextManager.findContext(CharacterInputContext.CONTEXT_ID);
		}
		return context;
	}
	
	//TODO
	public void showEditorInput(IEditorInput editorInput) {
		String name = editorInput.getName();
		String id = getActivePageInstance().getId();
		if (name.equals(ICoreConstants.BUILD_FILENAME_DESCRIPTOR)) {
			 if (name.equals(ICoreConstants.PLUGIN_FILENAME_DESCRIPTOR) || name.equals(ICoreConstants.FRAGMENT_FILENAME_DESCRIPTOR)) {
			if (!CharacterInputContext.CONTEXT_ID.equals(id)) {
				if (SHOW_SOURCE) {
					setActivePage(CharacterInputContext.CONTEXT_ID);
				
				} else {
					setActivePage(OverviewPage.PAGE_ID);
				}
			}
		} 
	}
	}
	
}
